﻿using Liang.DataBase.IDAL;
using Liang.DataBase.Model;
using Liang.DataBase.Model.Entity;
using Liang.DataBase.Tools;
using Liang.Model;
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace Liang.DataBase.DAL
{
    /// <summary>
    /// 数据访问层基类实现层
    /// </summary>
    /// <typeparam name="T">实体对象类型</typeparam>
    public abstract class BaseDAL<T> : IBaseDAL<T> where T : class
    {
        /// <summary>
        /// DbContext对象
        /// </summary>
        public DBEntities dbContext;

        /// <summary>
        /// 参数化构造函数
        /// </summary>
        /// <param name="context">DbContext对象</param>
        public BaseDAL()
        {
            dbContext = new DBEntities();
        }

        /// <summary>
        /// 插入指定对象到数据库中
        /// </summary>
        /// <param name="t">指定的对象</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c></returns>
        public virtual bool Insert(T t)
        {
            //ArgumentValidation.CheckForNullReference(t, "传入的对象t为空");
            dbContext.Set<T>().Add(t);
            return dbContext.SaveChanges() > 0;
        }

        /// <summary>
        /// 根据指定对象的ID,从数据库中删除指定对象
        /// </summary>
        /// <param name="id">对象的ID</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public virtual bool Delete(object id)
        {
            T obj = dbContext.Set<T>().Find(id);
            dbContext.Set<T>().Remove(obj);
            return dbContext.SaveChanges() > 0;
        }


        /// <summary>
        /// 从数据库中删除指定对象
        /// </summary>
        /// <param name="t">对象</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public virtual bool Delete(T t)
        {
            //ArgumentValidation.CheckForNullReference(t, "传入的对象t为空");
            dbContext.Set<T>().Remove(t);
            return dbContext.SaveChanges() > 0;
        }


        /// <summary>
        /// 更新对象属性到数据库中
        /// </summary>
        /// <param name="t">指定的对象</param>
        /// <param name="key">主键的值</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c></returns>
        public virtual bool Update(T t, object key)
        {
            //ArgumentValidation.CheckForNullReference(t, "传入的对象t为空");
            bool result = false;
            T existing = dbContext.Set<T>().Find(key);
            if (existing != null)
            {
                dbContext.Entry(existing).CurrentValues.SetValues(t);
                result = dbContext.SaveChanges() > 0;
            }
            return result;
        }

        /// <summary>
        /// 根据id查找返回对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T FindByID(object id)
        {
            return dbContext.Set<T>().Find(id);
        }

        /// <summary>
        /// 根据条件查询数据库,如果存在返回第一个对象
        /// </summary>
        /// <param name="match">条件表达式</param>
        /// <returns>存在则返回指定的第一个对象,否则返回默认值</returns>
        public virtual T FindSingle(Expression<Func<T, bool>> match)
        {
            return dbContext.Set<T>().FirstOrDefault(match);
        }

        /// <summary>
        /// 返回可查询的记录
        /// </summary>
        /// <returns></returns>
        public virtual IList<T> FindAll()
        {
            return dbContext.Set<T>().ToList<T>();
        }

        /// <summary>
        /// 根据条件查找返回记录
        /// </summary>
        /// <param name="match"></param>
        /// <returns></returns>
        public virtual IList<T> FindAll(Expression<Func<T, bool>> match)
        {
            return dbContext.Set<T>().Where(match).ToList<T>();
        }

        /// <summary>
        /// 根据条件表达式查询记录，并按指定列排序
        /// </summary>
        /// <param name="match">查询条件</param>
        /// <param name="propertyName">排序参数</param>
        /// <param name="isDesc">如果为true则为降序，否则为升序</param>
        /// <returns></returns>
        public virtual IList<T> FindWithOrderby(Expression<Func<T, bool>> match, string propertyName, bool isDesc = false)
        {
            var param = Expression.Parameter(typeof(T));
            var body = Expression.Property(param, propertyName);
            dynamic keySelector = Expression.Lambda(body, param);
            IQueryable<T> query = dbContext.Set<T>().Where(match);
            if (match != null)
            {
                query = query.Where(match);
            }
            query = isDesc ? Queryable.OrderByDescending(query, keySelector) : Queryable.OrderBy(query, keySelector);
            return query.ToList();
        }

        /// <summary>
        /// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
        /// </summary>
        /// <param name="match">条件表达式</param>
        /// <param name="info">分页实体</param>
        /// <param name="propertyName">排序参数</param>
        /// <param name="isDesc">是否降序排序</param>
        /// <returns>指定对象的集合</returns>
        public virtual IList<T> FindWithPagerAndOrderby(Expression<Func<T, bool>> match, ref PageInfo info, string propertyName, bool isDesc = false)
        {
            int pageindex = (info.CurrentPageIndex < 1) ? 1 : info.CurrentPageIndex;
            int pageSize = (info.PageSize <= 0) ? 20 : info.PageSize;

            int excludedRows = (pageindex - 1) * pageSize;
            var param = Expression.Parameter(typeof(T));
            var body = Expression.Property(param, propertyName);
            dynamic keySelector = Expression.Lambda(body, param);
            IQueryable<T> query = isDesc ? Queryable.OrderByDescending(dbContext.Set<T>().Where(match), keySelector) : Queryable.OrderBy(dbContext.Set<T>().Where(match), keySelector);

            info.RecordCount = query.Count();

            return query.Skip(excludedRows).Take(pageSize).ToList();
        }
    }
}
